﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using Microsoft.WindowsAzure.ServiceRuntime;
using FtpWorkerRole.FtpServer;

namespace FtpWorkerRole.AzureStorage
{
    public class AzureFileSystem : IFileSystem
    {
        public static string HIDDEN = ".hidden";
        //private string accountStr = "DefaultEndpointsProtocol=https;AccountName=firstblooddata;AccountKey=mgWEj3mTZekLK+79Q2HXC8ckw0rmAP7GD4E6ndilb/lMiCs00JxB983s9T6v8S/ApSi0b5OF35Uayg7M1v3vDA==";
        private CloudStorageAccount account;
        private CloudBlobClient blobClient;
        private string containerName;
        
        public AzureFileSystem(string container)
        {
            //account = CloudStorageAccount.DevelopmentStorageAccount;
            //account = CloudStorageAccount.Parse(accountStr);
            account = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(
                  "Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString"));
            blobClient = account.CreateCloudBlobClient();
            
            containerName = container.ToLower();
        }
        public IFile openFile(string path, bool download)
        {
            path = convertPrefix(path);
            var file = new AzureFile();            
            if (download)
            {
                file.File = new MemoryStream();
                var container = blobClient.GetContainerReference(containerName);
                container.CreateIfNotExist();
                try
                {
                    var blob = container.GetBlobReference(path);
                    blob.DownloadToStream(file.File);
                }
                catch (StorageClientException e)
                {
                    /*if (e.ErrorCode == StorageErrorCode.ResourceNotFound)
                    {
                        return null;
                    }*/
                    return null;
                }
            }            
            return file;
        }

        public void createDirectory(string path)
        {
            path = convertPrefix(path);
            var container = blobClient.GetContainerReference(containerName);
            container.CreateIfNotExist();
            string blobname = path + "/" +AzureFileSystem.HIDDEN;
            var blob = container.GetBlobReference(blobname);
            string message = "#REQUIRED: At least one file is required";
            blob.UploadText(message);
            var props = blob.Properties;
            props.ContentType = "text/text";
            blob.SetProperties();
        }
        public string[] listFiles(string path)
        {
            path = convertPrefix(path);
            if (!path.EndsWith("/") && path != "")
                path += "/";
            string prefix = string.Concat(containerName, "/", convertPrefix(path));

            var container = blobClient.GetContainerReference(containerName);
            container.CreateIfNotExist();
            var files = new List<AzureCloudFile>();
            files.AddRange(
                blobClient.ListBlobsWithPrefix(prefix).OfType<CloudBlob>().Select(
                    blob =>
                    new AzureCloudFile
                    {
                        Meta = blob.Metadata,
                        Uri = blob.Uri,
                        Size = blob.Properties.Length,
                        ContentType = blob.Properties.ContentType,
                        LastModified = blob.Properties.LastModifiedUtc
                    }));
            string[] result = new string[files.Count];
            int count = 0;
            foreach (AzureCloudFile f in files)
            {
                var monthStr = Utils.getMonth(f.LastModified.Month);
                var dayStr = f.LastModified.Day.ToString();                                    
                //dayStr =string.Format("{0:hh}", dayStr) + ":" + string.Format("{0:mm}", dayStr);
                var yearStr = f.LastModified.Year.ToString();
                var fname = Utils.getUriName(f.Uri);
                if (fname != AzureFileSystem.HIDDEN)
                {
                    string strTemp = "-rw-r--r-- 1 owner group " + f.Size + " "
                        + monthStr + "  " + dayStr + " " + yearStr + " " + fname;
                    result[count] = strTemp;
                    count++;
                }
            }
            return result;
        }
        public string[] listDirectories(string path)
        {
            path = convertPrefix(path);
            var container = blobClient.GetContainerReference(containerName);
            container.CreateIfNotExist();
            var directories = new List<AzureCloudDirectory>();
            if (path == "")
            {
                directories.AddRange(
                    container.ListBlobs().OfType<CloudBlobDirectory>().Select(
                        dir => new AzureCloudDirectory { path = dir.Uri }));

            }
            else
            {
                var parent = container.GetDirectoryReference(path);
                directories.AddRange(
                    parent.ListBlobs().OfType<CloudBlobDirectory>().Select(
                        dir => new AzureCloudDirectory { path = dir.Uri }));
            }

            var results = new string[directories.Count];
            int count = 0;
            foreach (AzureCloudDirectory d in directories)
            {
                var yearStr = DateTime.Today.Year.ToString();
                var monthStr = Utils.getMonth(DateTime.Today.Month);
                var dayStr = DateTime.Today.Day.ToString();
                var timestamp = string.Format("{0} {1} {2}", monthStr, dayStr, yearStr);
                var dname = d.path.ToString();
                dname = dname.Remove(dname.LastIndexOf(@"/"));
                dname = dname.Substring(dname.LastIndexOf(@"/") + 1);

                string strTemp = "drwxr-xr-x 1 owner group 1 "+timestamp+" "+ dname;
                results[count] = strTemp;
                count++;
            }
            return results;
        }

        public bool isFileExist(string path)
        {
            path = convertPrefix(path);
            var container = blobClient.GetContainerReference(containerName);
            container.CreateIfNotExist();
            var blob = container.GetBlobReference(path);

            try
            {
                blob.FetchAttributes();
                return true;
            }
            catch (StorageClientException e)
            {
                if (e.ErrorCode == StorageErrorCode.ResourceNotFound)
                {
                    return false;
                }
            }
            return false;
        }
        public bool isDirectoryExist(string path)
        {
            path = convertPrefix(path);
            if (path == "")
                return true;

            var container = blobClient.GetContainerReference(containerName);
            container.CreateIfNotExist();
            var dir = container.GetDirectoryReference(path);
            return dir.ListBlobs(new BlobRequestOptions { UseFlatBlobListing = true }).Count() > 0;
            /*IEnumerable<CloudBlobDirectory> results = 
                (from d in container.ListBlobs(new BlobRequestOptions{UseFlatBlobListing = true}).OfType<CloudBlobDirectory>()
                 where d.Uri.ToString().Contains(path)
                 select d);
            if (results.Count() > 0)
                return true;*/
            //return false;
        }

        public bool put(string path, IFile file)
        {
            path = convertPrefix(path);
            var container = blobClient.GetContainerReference(containerName);
            container.CreateIfNotExist();
            var blob = container.GetBlobReference(path);
            file.File.Seek(0, SeekOrigin.Begin);
            blob.UploadFromStream(file.File);
            return true;
        }

        public bool delete(string path)
        {
            path = convertPrefix(path);
            var container = blobClient.GetContainerReference(containerName);
            container.CreateIfNotExist();
            var blob = container.GetBlobReference(path);

            return blob.DeleteIfExists();
        }

        public bool deleteDirectory(string path)
        {
            path = convertPrefix(path);
            if (path == "")
                return false;

            var container = blobClient.GetContainerReference(containerName);
            container.CreateIfNotExist();
            var dir = container.GetDirectoryReference(path);
            int count =  dir.ListBlobs(new BlobRequestOptions { UseFlatBlobListing = true }).Count();
            if (count > 1)
            {
                return false;
            }
            var blob = container.GetBlobReference(path+"/"+AzureFileSystem.HIDDEN);
            return blob.DeleteIfExists();
        }

        private string convertPrefix(string path)
        {
            if (path.StartsWith(@"\") || path.StartsWith(@"/") || path.StartsWith(@"\\"))
                path = path.Remove(0, 1);
            return path.Replace(@"\", @"/");
        }
    }
}
